#include <string.h>
#include "param.h"
#include "z_memory.h"
#include "z_logger.h"

query_param_t *param_new() {
    return z_calloc(1, sizeof(query_param_t));
}

void param_free(query_param_t *ptr) {
    if (ptr) z_free(ptr);
}

const query_value_t *param_get_value(const query_param_t *param, const char *key);

const query_value_t *param_get_value(const query_param_t *param, const char *key) {
    if (NULL == param || NULL == key) return NULL;

    for (int i = 0; i < param->size; ++i) {
        if (!strcasecmp(key, param->key[i])) {
            return &param->val[i];
        }
    }

    return NULL;
}

const char *param_get_string(const query_param_t *param, const char *key) {
    static const char *_empty_str = "";

    const query_value_t *value = param_get_value(param, key);
    if (NULL != value) {
        if (cJSON_String == value->type) {
            return value->str_val;
        } else {
            return _empty_str;
        }
    } else {
        return _empty_str;
    }
}

const char *param_get_method(const query_param_t *param) {
    return param_get_string(param, PARAM_METHOD);
}

_Bool param_method_is(const query_param_t *param, const char *method) {
    return 0 == strcasecmp(method, param_get_method(param));
}

const char *param_get_table(const query_param_t *param) {
    return param_get_string(param, PARAM_TABLE);
}

const char *param_get_key(const query_param_t *param) {
    return param_get_string(param, PARAM_KEY);
}

const char *param_get_segment(const query_param_t *param) {
    return param_get_string(param, PARAM_SEGMENT);
}

const char *param_get_tag(const query_param_t *param) {
    return param_get_string(param, PARAM_TAG);
}

int param_parse_query(query_param_t *param, const char *query) {
    if (NULL == param || NULL == query) return -1;

    log_debug("query=[%s]", query);

    char *save_ptr = NULL;
    char *p = strtok_r(query, "&", &save_ptr);
    for (int i = 0; NULL != p && param->size < PARAM_MAX; ++i) {
        param->key[param->size] = p;
        query_value_t *value = &param->val[param->size];
        char *p1 = strchr(p, '=');
        if (NULL != p1) {
            *p1 = '\0';
            value->type = cJSON_String;
            value->str_val = p1 + 1;
        }

        log_trace("key=%s, val=%s", param->key[param->size], value->str_val);
        param->size++;

        p = strtok_r(NULL, "&", &save_ptr);
    }
    return param->size;
}

int param_parse_cjson(query_param_t *param, const cJSON *cjson) {
    if (NULL == param || NULL == cjson) return -1;

    for (int i = 0; i < cJSON_GetArraySize(cjson) && param->size < PARAM_MAX; ++i) {
        cJSON *item = cJSON_GetArrayItem(cjson, i);
        param->key[param->size] = item->string;

        query_value_t *value = &param->val[param->size];

        if (cJSON_String == item->type) {
            value->type = cJSON_String;
            value->str_val = item->valuestring;
            log_trace("key=%s, val=%s", param->key[param->size], value->str_val);
        } else if (cJSON_Number == item->type) {
            value->type = cJSON_Number;
            value->dbl_val = item->valuedouble;
            log_trace("key=%s, val=%f", param->key[param->size], value->dbl_val);
        } else if (cJSON_True == item->type) {
            value->type = cJSON_Number;
            value->dbl_val = 1.0;
            log_trace("key=%s, val=True", param->key[param->size]);
        } else if (cJSON_False == item->type) {
            value->type = cJSON_Number;
            value->dbl_val = 0.0;
            log_trace("key=%s, val=False", param->key[param->size]);
        } else {
            value->type = cJSON_NULL;
            value->raw_val = NULL;
            log_trace("key=%s, val=Null", param->key[param->size]);
        }

        param->size++;
    }
    return param->size;
}



